import asyncio
from typing import Any, Dict

import pytest
from unittest.mock import Mock, AsyncMock

# 导入待测试模块
from src.mcp import standard_interface as si
from src.mcp.tools import MCPTools


import pytest_asyncio

@pytest_asyncio.fixture(scope="module")
async def setup_standard_interface():
    """构造假的 orchestrator 并注入 standard_interface"""
    # 使用 Mock 代替真正的 ContextOrchestrator
    orchestrator = Mock()

    # 初始化 MCPTools，并覆盖所有工具处理函数为简单回显
    tools = MCPTools(orchestrator)
    for name, meta in tools.tools.items():
        async def _echo(args: Dict[str, Any], _n=name):  # noqa: B023 (闭包默认值绑定)
            return {"echo": _n, "received": args}

        # 替换 handler
        meta["handler"] = _echo  # type: ignore[assignment]

    # 将我们准备好的 orchestrator 注入 standard_interface
    si.set_orchestrator(orchestrator)  # 这一步会刷新 _TOOLS
    # 覆盖 si._TOOLS 为我们自定义的 MCPTools 实例
    si._TOOLS = tools  # type: ignore[attr-defined]
    # 重新生成包装函数，确保指向新的 _TOOLS
    si.refresh_wrappers()

    yield  # 测试运行


@pytest.mark.asyncio
async def test_包装函数与call_tool一致(setup_standard_interface):
    """遍历所有工具，检查包装函数结果与 call_tool 结果一致"""
    # 遍历 standard_interface 当前可用工具
    for name, meta in si._TOOLS.tools.items():  # type: ignore[attr-defined]
        schema = meta["inputSchema"]
        required = schema.get("required", [])
        properties = schema.get("properties", {})

        # 为必需参数构造占位值
        dummy_args: Dict[str, Any] = {}
        for field in required:
            field_type = properties[field]["type"]
            if field_type == "string":
                dummy_args[field] = "dummy"
            elif field_type == "integer":
                dummy_args[field] = 1
            elif field_type == "number":
                dummy_args[field] = 1.0
            elif field_type == "boolean":
                dummy_args[field] = True
            elif field_type == "array":
                dummy_args[field] = []
            elif field_type == "object":
                dummy_args[field] = {}
            else:
                dummy_args[field] = None

        # 获取包装函数
        wrapper_fn = getattr(si, name)
        res_wrapper = await wrapper_fn(**dummy_args)
        res_direct = await si._TOOLS.call_tool(name, dummy_args)  # type: ignore[attr-defined]

        assert res_wrapper == res_direct, f"接口不一致: {name}"